﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace LiteFramework
{
    [Serializable]
    [ComVisible(true)]
    [XmlType(TypeName = "KeyedBag", Namespace = SystemResources.NS)]
    [XmlRoot(ElementName = "KeyedBag", Namespace = SystemResources.NS, IsNullable = true)]
    [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
    public sealed class KeyedBag : Bag, ICloneable  //, ICollection 不能 XmlSerializable
    {
        [XmlAttribute()]
        public string Name = String.Empty;

        public KeyedBag()
            : base()
        {
        }

        public KeyedBag(string name)
            : base()
        {
            this.Name = name;
        }

        public KeyedBag(Guid guid)
            : base(guid)
        {
        }

        public KeyedBag(DataRow dataRow)
            : base(dataRow)
        {
        }

        public KeyedBag(Bag bag)
            : base(bag.Guid, bag.element)
        {
            this.Name = bag.GetType().Name;
        }

        #region Copy

        public KeyedBag Copy()
        {
            KeyedBag kb = new KeyedBag();
            this.CopyTo(kb);

            return kb;
        }

        #endregion

        #region ICloneable 成员

        object ICloneable.Clone()
        {
            return this.Copy();
        }

        #endregion

        #region GetValuesByKey

        public static object[] GetValuesByKey(KeyedBag[] kbs, string key)
        {
            return KeyedBag.GetValuesByKey(kbs, key, false);
        }

        public static object[] GetValuesByKey(KeyedBag[] kbs, string key, bool suppressRepeat)
        {
            List<object> list = new List<object>();

            foreach (KeyedBag kb in kbs)
            {
                object obj = kb.GetValue(key);
                if (suppressRepeat)
                {
                    if (obj != null && !list.Contains(obj))
                    {
                        list.Add(obj);
                    }
                }
                else
                {
                    list.Add(obj);
                }
            }

            return list.ToArray();
        }

        #endregion

        #region ToTable

        //public static KeyedBag[] FromTable(DataTable table)
        //{
        //    if (table != null)
        //    {
        //        List<KeyedBag> list = new List<KeyedBag>(table.Rows.Count);
        //        foreach (DataRow row in table.Rows)
        //        {
        //            list.Add(new KeyedBag(row));
        //        }
        //        return list.ToArray();
        //    }
        //    else
        //    {
        //        return new KeyedBag[] { };
        //    }
        //}

        public static DataTable ToTable(KeyedBag[] list)
        {
            return KeyedBag.ToTable(list, false);
        }

        public static DataTable ToTable(KeyedBag[] list, bool complex)
        {
            return Bag.ToTable<KeyedBag>(list, complex);
        }

        #endregion

        #region IndexOf
        public static int IndexOf(KeyedBag[] array, KeyedBag value)
        {
            return Bag.IndexOf(array, value);
        }
        #endregion

        #region Deserialize

        //public static KeyedBag Deserialize(string fileName)
        //{
        //    return Bag.Deserialize<KeyedBag>(fileName);
        //}

        //public static KeyedBag Deserialize(Stream stream)
        //{
        //    return Bag.Deserialize<KeyedBag>(stream);
        //}

        //public static KeyedBag Deserialize(string fileName, IFormatter formatter)
        //{
        //    return Bag.Deserialize<KeyedBag>(fileName, formatter);
        //}

        //public new static KeyedBag Deserialize(Stream stream, IFormatter formatter)
        //{
        //    return Bag.Deserialize<KeyedBag>(stream, formatter);
        //}

        #endregion

        #region Xml

        //public static KeyedBag ReadXml(Stream stream)
        //{
        //    return Bag.ReadXml<KeyedBag>(stream);
        //}

        //public static KeyedBag ReadXml(XmlReader reader)
        //{
        //    return Bag.ReadXml<KeyedBag>(reader);
        //}

        //public static KeyedBag ReadXml(string fileName)
        //{
        //    return Bag.ReadXml<KeyedBag>(fileName);
        //}

        #endregion

        #region 属性

        [XmlAttribute()]
        public new Guid Guid
        {
            get
            {
                return base.Guid;
            }
            set
            {
                base.Guid = value;
            }
        }

        [XmlElement()]
        public HashtableSerializationProxy Element
        {
            get
            {
                return base.element;
            }
        }

        [XmlIgnore()]
        public new object this[string key]
        {
            get
            {
                return base[key];
            }
            set
            {
                base[key] = value;
            }
        }

        [XmlIgnore()]
        public string[] Keys
        {
            get
            {
                return base.GetKeys();
            }
        }

        [XmlIgnore()]
        public object[] Values
        {
            get
            {
                return base.GetValues();
            }
        }

        #endregion

        #region Get, Set, Remove, Clear

        public new object GetValue(string key)
        {
            return base.GetValue(key);
        }

        public new string GetValue(string key, string defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new bool GetValue(string key, bool defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new long GetValue(string key, long defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new int GetValue(string key, int defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new int GetValue(string key, short defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new decimal GetValue(string key, decimal defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new float GetValue(string key, float defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new double GetValue(string key, double defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new sbyte GetValue(string key, sbyte defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new DateTime GetValue(string key, DateTime defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new TimeSpan GetValue(string key, TimeSpan defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new object GetValue(string key, object defaultValue)
        {
            return base.GetValue(key, defaultValue);
        }

        public new void SetValue(string key, object value)
        {
            base.SetValue(key, value);
        }

        public new void Remove(string key)
        {
            base.Remove(key);
        }

        public new void Clear()
        {
            base.Clear();
        }

        public new void SetNull(string key)
        {
            base.SetNull(key);
        }

        public new bool IsNull(string key)
        {
            return base.IsNull(key);
        }

        public new bool HasKey(string key)
        {
            return base.HasKey(key);
        }

        #endregion
    }
}
